package com.violet.myorm.core.execute;

import com.violet.myorm.Model;
import com.violet.myorm.annotations.PrimaryKey;
import com.violet.myorm.core.combination.CreateCombination;
import com.violet.myorm.core.condition.SerializableFunction;
import com.violet.myorm.core.source.Reflect;
import com.violet.myorm.core.sql.InsertSql;
import com.violet.myorm.core.sql.Sql;
import com.violet.myorm.utils.SqlUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

public class Insert<E>
    extends BaseExecute
    implements CreateCombination<Insert<E>>
{
    private final Class<E> clazz;

    private final List<Field> fields;
    private final Field primary;
    private final List<Object> values;

    public Insert(Class<E> clazz) {
        this.clazz = clazz;
        this.fields = Reflect.getNormFields(clazz);
        this.values = new ArrayList<>();
        this.primary = Reflect.getPrimaryKey(clazz);
    }

    @Override
    public Insert<E> insert(Model... entities) {
        for (Model entity : entities) {
            for (Field field : fields) {
                try {
                    if (field.equals(primary)) {
                        switch (field.getAnnotation(PrimaryKey.class).state()) {
                            case AUTO -> values.add(null);
                            case NONE -> values.add(field.get(entity));
                        }
                    }
                    else values.add(field.get(entity));
                }
                catch (IllegalAccessException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return this;
    }

    @Override
    public int executeCreate() {
        List<String> names = new ArrayList<>(fields.size());
        for (Field field : fields) names.add(Reflect.getFieldName(field));
        InsertSql create = SqlUtils.createInsert(clazz, names);
        create.insert(fields.size(), values.size());
        return executeUpdate(create, values, List.of());
    }
}
